import os
from flask import Flask, session, redirect, url_for, request
from models import db
from models.user import User
from services.user_service import UserService
from controllers.user_controller import UserController
from routes import init_routes
from routes.views import views_bp
from config import config
from .container import Container
from flask_migrate import Migrate

def create_app(config_name=None):
    """应用工厂函数"""
    if config_name is None:
        config_name = os.environ.get('FLASK_CONFIG', 'default')
    
    app = Flask(__name__)
    app.config.from_object(config[config_name])

    # 设置模板和静态文件目录
    basedir = os.path.abspath(os.path.dirname(__file__))
    app.template_folder = os.path.join(basedir, '..', 'templates')
    app.static_folder = os.path.join(basedir, '..', 'static')

    # 初始化数据库
    db.init_app(app)
    migrate = Migrate(app, db)  # 关键：绑定 migrate

    # 初始化模型
    with app.app_context():
        UserClass = User.init_db(db)
        db.create_all()

    # 创建依赖注入容器
    container = Container()
    
    # 注册服务到容器
    user_service = UserService(UserClass)
    container.register_service('user', user_service)
    
    # 注册控制器到容器
    user_controller = UserController(user_service)
    container.register_controller('user', user_controller)

    # 初始化路由，传递整个容器
    init_routes(app, container)
    
    # 注册视图蓝图
    app.register_blueprint(views_bp)
    
    # 添加请求前处理函数，检查登录状态
    @app.before_request
    def check_login():
        # 不需要登录检查的路径
        exempt_paths = ['/login', '/register', '/api/users/login', '/api/users/register', '/api/users/logout', '/static/']
        
        # 检查当前路径是否在豁免列表中
        path = request.path
        if any(path.startswith(exempt) for exempt in exempt_paths):
            return None
            
        # 检查是否已登录
        if 'user_id' not in session:
            # 如果是API请求，返回JSON响应
            if path.startswith('/api/'):
                return {
                    'code': 1,
                    'message': '未登录，请先登录'
                }, 401
            # 如果是页面请求，重定向到登录页
            else:
                return redirect(url_for('views.login'))

    return app